package it.yuzuojian.com.util;

import it.yuzuojian.com.annotation.aop.Aspect;
import it.yuzuojian.com.annotation.ioc.Scope;
import it.yuzuojian.com.annotation.mvc.Controller;
import it.yuzuojian.com.handle.mvc.DateHandle;
import it.yuzuojian.com.handle.mvc.WebMvcConfigurer;
import it.yuzuojian.com.handleiInterface.BeanPostProcessor;
import it.yuzuojian.com.pojo.BeanDefinition;
import it.yuzuojian.com.pojo.BeanFactory;
import it.yuzuojian.com.pojo.BeanPostProcessorOrder;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class BeanFactoryUtil {
    private static List<BeanPostProcessorOrder> beanPostProcessorOrders = new ArrayList<>();
    private BeanFactory beanFactory = new BeanFactory();
    public void setBeanDefinition(Class clazz) {
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setClazz(clazz);
        beanDefinition.setBeanName(clazz.getSimpleName());
        if (clazz.isAnnotationPresent(Scope.class)) {
            Scope declaredAnnotation = (Scope) clazz.getDeclaredAnnotation(Scope.class);
            if (declaredAnnotation.value().equals("")) {
                beanDefinition.setScope("singleton");
            } else {
                beanDefinition.setScope(declaredAnnotation.value());
            }
        } else {
            beanDefinition.setScope("singleton");
        }
        if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
            beanDefinition.setBeanPostProcessor(true);
        } else {
            beanDefinition.setBeanPostProcessor(false);
        }
        if (DateHandle.class.isAssignableFrom(clazz)) {
            beanDefinition.setDateHandle(true);
        } else {
            beanDefinition.setDateHandle(false);
        }
        if (WebMvcConfigurer.class.isAssignableFrom(clazz)) {
            beanDefinition.setWebMvcConfigurer(true);
        } else {
            beanDefinition.setWebMvcConfigurer(false);
        }
        if(clazz.isAnnotationPresent(Aspect.class)){
            beanDefinition.setAspect(true);
        }else {
            beanDefinition.setAspect(false);
        }
        if(clazz.isAnnotationPresent(Controller.class)){
            beanDefinition.setController(true);
        }else {
            beanDefinition.setController(false);
        }
        beanFactory.setBeanDefinition(beanDefinition);


    }

    public void setBeanDefinition(Class clazz, String beanName) {
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setClazz(clazz);
        beanDefinition.setBeanName(beanName);
        if (clazz.isAnnotationPresent(Scope.class)) {
            Scope declaredAnnotation = (Scope) clazz.getDeclaredAnnotation(Scope.class);
            if (declaredAnnotation.value().equals("")) {
                beanDefinition.setScope("singleton");
            } else {
                beanDefinition.setScope(declaredAnnotation.value());
            }
        } else {
            beanDefinition.setScope("singleton");
        }
        if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
            beanDefinition.setBeanPostProcessor(true);
        } else {
            beanDefinition.setBeanPostProcessor(false);
        }
        if (DateHandle.class.isAssignableFrom(clazz)) {
            beanDefinition.setDateHandle(true);
        } else {
            beanDefinition.setDateHandle(false);
        }
        if(clazz.isAnnotationPresent(Aspect.class)){
            beanDefinition.setAspect(true);
        }else {
            beanDefinition.setAspect(false);
        }
        if(clazz.isAnnotationPresent(Controller.class)){
            beanDefinition.setController(true);
        }else {
            beanDefinition.setController(false);
        }
        beanFactory.setBeanDefinition(beanDefinition);

    }

    public BeanDefinition getBeanDefinition(String beanName) {
        return beanFactory.getBeanDefinition(beanName);

    }

    public List<BeanDefinition> getBeanDefinition(Class clazz) {
        ConcurrentHashMap<String, BeanDefinition> beanDefinitions = beanFactory.getBeanDefinitions();
        List<BeanDefinition> objects = new ArrayList<>();
        beanDefinitions.forEach((beanName, beanDefinition) -> {
            if (clazz.isAssignableFrom(beanDefinition.getClazz())) {
                objects.add(beanDefinition);
            }
        });
        return objects;

    }

    public void setOriginalObject(BeanDefinition beanDefinition) throws InstantiationException, IllegalAccessException {
        beanFactory.setOriginalObject(beanDefinition.getBeanName(), beanDefinition.getClazz().newInstance());

    }

    public void setOriginalObject(String beanName, Object object) {
        beanFactory.setOriginalObject(beanName, object);

    }

    public Object getOriginalObject(String beanName) {
        return beanFactory.getOriginalObject(beanName);
    }

    public List<Object> getOriginalObject(Class clazz) {
        ConcurrentHashMap<String, Object> originalObjects = beanFactory.getOriginalObjects();
        List<Object> objects = new ArrayList<>();
        originalObjects.forEach((beanName, originalObject) -> {
            if (clazz.isAssignableFrom(originalObject.getClass())) {
                objects.add(originalObject);
            }
        });
        return objects;
    }

    public void setSingletonObject(String beanName, Object object) {
        beanFactory.setSingletonObjects(beanName, object);
    }


    public Object getSingletonObject(String beanName) {
        return beanFactory.getSingletonObject(beanName);
    }

}
